
const path                   = require('path');
const webpack                = require('webpack');
const CopyWebpackPlugin      = require("copy-webpack-plugin");
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const RemovePlugin           = require('remove-files-webpack-plugin');
const ZipPlugin              = require('zip-webpack-plugin');

const ENVIRONMENT = process.env.NODE_ENV || "development";
const IS_PRODUCTION  = (ENVIRONMENT === "production");
const IS_DEVELOPMENT = (ENVIRONMENT === "development");


// "chrome" or "firefox"
const PLATFORM = process.env.MX_PLATFORM;

// PLATFORM_ID is only used in production environment.
//   - on Firefox, platform id is extension's id (generated by AMO).
//   - on Chrome, platform id is the public key (generated by Chrome Webstore).
const PLATFORM_ID = process.env.MX_PLATFORM_ID;

const manifest = require("./src/manifest.json");

const pages_folder = path.join(__dirname, "src", "pages");
const dist_folder  = path.join(__dirname, "dist", "extension", "maoxian-web-clipper");
const npm_folder   = path.join(__dirname, "node_modules");

// extension page names
const pages = [
  'background', 'popup', 'welcome', 'history', 'home', 'last-clipping-result',
  'plan-subscription', 'reset-history', 'setting', 'support',
  'ui-control', 'ui-selection', 'failed-tasks',  'debug'];

function getCopyItems() {

  const items = [];

  // 3rd party js and css
  [
    ['webextension-polyfill/dist/browser-polyfill.js', 'vendor/js/browser-polyfill.js'],
    ['roddeh-i18n/dist/i18n.js'    , 'vendor/js/i18n.js']          ,
    ['awesomplete/awesomplete.js'  , 'vendor/js/awesomplete.js']   ,
    ['pikaday/pikaday.js'          , 'vendor/js/pikaday.js']       ,

    ['awesomplete/awesomplete.css' , 'vendor/css/awesomplete.css'] ,
    ['pikaday/css/pikaday.css'     , 'vendor/css/pikaday.css']     ,
  ].forEach((pair) => {
    const sourceFilename = path.join(npm_folder, pair[0]);
    const targetFilename = path.join(dist_folder, pair[1]);
    items.push({from: sourceFilename, to: targetFilename});
  });

  // page assets
  [
    /* icons and locale files */
    ['src/icons', 'icons'],
    ['src/_locales/en',    '_locales/en' ],
    ['src/_locales/zh_CN', '_locales/zh_CN' ],
    ['src/_locales/pikaday.i18n.js', '_locales/pikaday.i18n.js' ],

    /* page libs */
    ['src/js/lib/log.js'               , 'js/lib/log.js']               ,
    ['src/js/lib/tool.js'              , 'js/lib/tool.js']              ,
    ['src/js/lib/icon.js'              , 'js/lib/icon.js']              ,
    ['src/js/lib/translation.js'       , 'js/lib/translation.js']       ,
    ['src/js/lib/ext-api.js'           , 'js/lib/ext-api.js']           ,
    ['src/js/lib/ext-msg.js'           , 'js/lib/ext-msg.js']           ,
    ['src/js/lib/storage.js'           , 'js/lib/storage.js']           ,
    ['src/js/lib/config.js'            , 'js/lib/config.js']            ,
    ['src/js/lib/link.js'              , 'js/lib/link.js']              ,
    ['src/js/lib/template.js'          , 'js/lib/template.js']          ,
    ['src/js/lib/handler.js'           , 'js/lib/handler.js']           ,
    ['src/js/lib/frame-msg.js'         , 'js/lib/frame-msg.js']         ,
    ['src/js/lib/notify.js'            , 'js/lib/notify.js']            ,
    ['src/js/lib/query.js'             , 'js/lib/query.js']             ,
    ['src/js/lib/event-target.js'      , 'js/lib/event-target.js']      ,
    ['src/js/lib/fetcher-using-xhr.js' , 'js/lib/fetcher-using-xhr.js'] ,
    ['src/js/lib/action-cache.js'      , 'js/lib/action-cache.js']      ,
    ['src/js/lib/qwebchannel.js'       , 'js/lib/qwebchannel.js']       ,

    /* background */
    ['src/js/handler'                      , 'js/handler']                      ,
    ['src/js/saving'                       , 'js/saving']                       ,
    ['src/js/background'                   , 'js/background']                   ,
    ['src/js/clipping/backend.js'          , 'js/clipping/backend.js']          ,
    ['src/js/assistant/backend.js'         , 'js/assistant/backend.js']         ,
    ['src/js/assistant/plan-repository.js' , 'js/assistant/plan-repository.js'] ,
    ['src/js/assistant/fuzzy-matcher.js'   , 'js/assistant/fuzzy-matcher.js']   ,
    ['src/js/selection/backend.js'         , 'js/selection/backend.js']         ,
    ['src/js/selection/store.js'           , 'js/selection/store.js']           ,
  ].forEach((pair) => {
    const sourceFilename = pair[0];
    const targetFilename = path.join(dist_folder, pair[1]);
    items.push({from: sourceFilename, to: targetFilename});
  })

  // page htmls
  pages.forEach((name) => {
    const sourceFilename = `src/pages/${name}.html`;
    const targetFilename = path.join(dist_folder, `pages/${name}.html`);
    items.push({from: sourceFilename, to: targetFilename});
  });

  // page javascripts
  ['reset-history-worker'].concat(pages).forEach((name) => {
    const sourceFilename = `src/pages/${name}.js`;
    const targetFilename = path.join(dist_folder, `pages/${name}.js`);
    items.push({from: sourceFilename, to: targetFilename});
  });


  // page stylesheets
  const cssBlackList = ['ui-selection', 'background'];
  const cssNames = ['_base'].concat(pages);
  cssNames.forEach((name) => {
    if (cssBlackList.indexOf(name) == -1) {
      items.push({
        from: `src/pages/${name}.css`,
        to: path.join(dist_folder, `pages/${name}.css`),
      });
    }
  });

  // manifest
  items.push({
    from: 'src/manifest.json',
    to: path.join(dist_folder, 'manifest.json'),
    transform: (IS_PRODUCTION ? renderManifestWithPlatformMsg : renderManifest),
  });

  // env
  items.push({
    from: (IS_PRODUCTION ? 'src/js/env.production.js' : 'src/js/env.js'),
    to: path.join(dist_folder, 'js/env.js'),
  });

  return items;
}

const config = {
  mode: ENVIRONMENT,
  entry: {
    'content-frame' : path.join(__dirname, "src", "js", "content-frame.js"),
    'content'       : path.join(__dirname, "src", "js", "content.js"),
  },
  output: {
    filename: "js/[name].js",
    path: dist_folder
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-env'],
              plugins: [
                '@babel/plugin-transform-regenerator',
                "@babel/plugin-transform-runtime"],
              cacheDirectory: true
            }
          }
        ]
      },
    ]
  },
  plugins: [
    new CopyWebpackPlugin(getCopyItems(), { copyUnmodified: true }),
    new webpack.NormalModuleReplacementPlugin(
      /js\/env\.js/,
      (IS_PRODUCTION ? 'env.production.js' : 'env.js')
    ),
  ],
}



function renderManifest(content, path) {
  let manifest = JSON.parse(content.toString());
  return Buffer.from(JSON.stringify(manifest, null, 2));
}

function renderManifestWithPlatformMsg(content, path) {
  let manifest = JSON.parse(content.toString());
  switch(PLATFORM) {
    case 'chrome':
      manifest.key = PLATFORM_ID;  // Public key
      break;
    case 'firefox':
      manifest.applications = {
        gecko: {id: PLATFORM_ID}   // Extension id
      }
      break;
    default: break;
  }
  return Buffer.from(JSON.stringify(manifest, null, 2));
}

if (IS_PRODUCTION) {

  const zipfile = `maoxian-web-clipper-${PLATFORM}-${manifest.version}.zip`
  config.plugins.push(
    // Clean dist/extension/maoxian-web-clipper before every build.
    new CleanWebpackPlugin(),
    // Remove last zip files
    new RemovePlugin({
      before: {
        root: path.resolve('dist', 'extension'),
        include: [
          zipfile
        ]
      }
    }),
    // Compress dist/extension/maoxian-web-clipper
    new ZipPlugin({
      // Relative to Webpack output path
      path: '../',
      filename: zipfile,
    })
  );
} else if (ENVIRONMENT == "development") {
  config.devtool = 'inline-source-map';
}

module.exports = config
